﻿using Communergy.Repository.InMemory;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using Communergy.Common;
using System.Collections.Generic;
using System.Linq;

namespace Communergy.Repository.InMemory.Tests
{
    
    
    /// <summary>
    ///This is a test class for InMemoryEnergyDataRepositoryTest and is intended
    ///to contain all InMemoryEnergyDataRepositoryTest Unit Tests
    ///</summary>
    [TestClass()]
    public class InMemoryEnergyDataRepositoryTest
    {


        [TestMethod()]
        public void InMemoryEnergyDataRepository_AddEnergyData_ShouldBePendingSource()
        {

            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeterWithSource();
            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();

            
                          
            string sourceId = meterToCreate.Sources[0].Id;
            List<EnergyData> simpleEnergyDataList = InMemoryTestHelpers.SimpleEnergyDataList();
         

            InMemoryEnergyDataRepository energyRepository = new InMemoryEnergyDataRepository(unitOfWork);
            
            energyRepository.SaveEnergyData(sourceId, simpleEnergyDataList);

            var pendingData = unitOfWork.PendingEnergyDatum;
            var currentSourcePending = pendingData.Any(s => s.MeterSource.Id == sourceId);
            Assert.IsTrue(currentSourcePending);

        }

        [TestMethod()]
        public void InMemoryEnergyDataRepository_AddEnergyDataAndSave_ShouldBeNotBePending()
        {

            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeterWithSource();
            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();

            string sourceId = meterToCreate.Sources[0].Id;
            List<EnergyData> simpleEnergyDataList = InMemoryTestHelpers.SimpleEnergyDataList();
            
            InMemoryEnergyDataRepository energyRepository = new InMemoryEnergyDataRepository(unitOfWork);
            
            energyRepository.SaveEnergyData(sourceId, simpleEnergyDataList);
            unitOfWork.Save();

            var pendingData = unitOfWork.PendingEnergyDatum;
            var currentSourcePending = pendingData.Any(s => s.MeterSource.Id == sourceId);
            Assert.IsFalse(currentSourcePending);

        }



        [TestMethod()]
        public void InMemoryEnergyDataRepository_AddEnergyDataAndSave_NewDataAttachedToCorrectSource()
        {
            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeterWithSource();
            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();
            string sourceId = meterToCreate.Sources[0].Id;
            List<EnergyData> simpleEnergyDataList = InMemoryTestHelpers.SimpleEnergyDataList();
            InMemoryEnergyDataRepository energyRepository = new InMemoryEnergyDataRepository(unitOfWork);

            energyRepository.SaveEnergyData(sourceId, simpleEnergyDataList);
            unitOfWork.Save();

            var requiredSource = unitOfWork.RetrieveSourceDetails(sourceId);
            var attachedEnergyData = unitOfWork.SavedEnergyDatum.Where(ed => ed.MeterSource.Id == sourceId).FirstOrDefault().EnergyDatum; ;
            Assert.AreEqual(simpleEnergyDataList.Count, attachedEnergyData.Count);
            

        }


        [TestMethod()]
        public void InMemoryEnergyDataRepository_AddMultipleEnergyDataAndSave_NewDataAttachedToCorrectSource()
        {
            using (MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork())
            {
                InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
                Meter meterToCreate = InMemoryTestHelpers.GetTestMeterWithSource();
                meterRepository.CreateNewMeter(meterToCreate);
                unitOfWork.Save();
                string sourceId = meterToCreate.Sources[0].Id;
                int energyItems = 20;
                var energyData = InMemoryTestHelpers.MultipleEnergyDataItems(DateTime.Now, new TimeSpan(0, 0, 6), energyItems, 100);
                InMemoryEnergyDataRepository energyRepository = new InMemoryEnergyDataRepository(unitOfWork);
                energyRepository.SaveEnergyData(sourceId, energyData);
                unitOfWork.Save();
                var requiredSource = unitOfWork.RetrieveSourceDetails(sourceId);
                var attachedEnergyData = unitOfWork.SavedEnergyDatum.Where(ed => ed.MeterSource.Id == sourceId).FirstOrDefault().EnergyDatum;
                ; ;
                Assert.AreEqual(energyItems, attachedEnergyData.Count);
            }

        }


        [TestMethod()]
        public void InMemoryEnergyDataRepository_AddTwoMultipleEnergyDataAndSave_NewDataAttachedToCorrectSource()
        {
            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeterWithSource();
            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();
            string sourceId = meterToCreate.Sources[0].Id;

            int energyItems = 20;
            var energyDataToday = InMemoryTestHelpers.MultipleEnergyDataItems(DateTime.Now, new TimeSpan(0, 0, 6), energyItems, 100);
            var energyDataTomorrow = InMemoryTestHelpers.MultipleEnergyDataItems(DateTime.Now.AddDays(1), new TimeSpan(0, 0, 6), energyItems, 100);
            InMemoryEnergyDataRepository energyRepository = new InMemoryEnergyDataRepository(unitOfWork);

            energyRepository.SaveEnergyData(sourceId, energyDataToday);
            energyRepository.SaveEnergyData(sourceId, energyDataTomorrow);

            unitOfWork.Save();

            var requiredSource = unitOfWork.RetrieveSourceDetails(sourceId);
            var attachedEnergyData = unitOfWork.SavedEnergyDatum.Where(ed => ed.MeterSource.Id == sourceId).FirstOrDefault().EnergyDatum;
            Assert.AreEqual(energyItems * 2, attachedEnergyData.Count());

        }

        [TestMethod()]
        public void InMemoryEnergyDataRepository_AddTwoMultipleEnergyDataStaggeredSave_NewDataAttachedToCorrectSource()
        {
            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeterWithSource();
            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();
            string sourceId = meterToCreate.Sources[0].Id;

            int energyItemsFirst = 20;
            var energyDataToday = InMemoryTestHelpers.MultipleEnergyDataItems(DateTime.Now, new TimeSpan(0, 0, 6), energyItemsFirst, 100);
           
            InMemoryEnergyDataRepository energyRepository = new InMemoryEnergyDataRepository(unitOfWork);

            energyRepository.SaveEnergyData(sourceId, energyDataToday);
            unitOfWork.Save();
            int energyItemsTomorrow = 30;
            var energyDataTomorrow = InMemoryTestHelpers.MultipleEnergyDataItems(DateTime.Now.AddDays(1), new TimeSpan(0, 0, 6), energyItemsTomorrow, 100);
            energyRepository.SaveEnergyData(sourceId, energyDataTomorrow);


            var attachedEnergyData = unitOfWork.SavedEnergyDatum.Where(ed => ed.MeterSource.Id == sourceId).FirstOrDefault().EnergyDatum;
            Assert.AreEqual(energyItemsFirst, attachedEnergyData.Count());            

        }


        [TestMethod()]
        public void InMemoryEnergyDataRepository_GetRawData_NewDataAttachedToCorrectSource()
        {
            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeterWithSource();
            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();
            string sourceId = meterToCreate.Sources[0].Id;

            int energyItemsCount = 60;
            DateTime startDate = InMemoryTestHelpers.START_DATE;
            var energyDataToday = InMemoryTestHelpers.MultipleEnergyDataItems(startDate, new TimeSpan(0, 1, 0), energyItemsCount, 100);

            InMemoryEnergyDataRepository energyRepository = new InMemoryEnergyDataRepository(unitOfWork);

            energyRepository.SaveEnergyData(sourceId, energyDataToday);
            unitOfWork.Save();
            
            int energyStartPoint = 10;
            int energyRange = 30;
            var queryStartDate = startDate.AddMinutes(energyStartPoint);
            var queryEndDate = startDate.AddMinutes(energyStartPoint + energyRange);
            var getRawData = energyRepository.GetRawEnergyData(sourceId, queryStartDate, queryEndDate);

            Assert.AreEqual(energyRange, getRawData.Count);
        }


        [TestMethod()]
        public void InMemoryEnergyDataRepository_AddSameEnergyDataTwiceAndSave_NewDataOnlyShowedOnce()
        {
            using (MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork())
            {
                InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
                Meter meterToCreate = InMemoryTestHelpers.GetTestMeterWithSource();
                meterRepository.CreateNewMeter(meterToCreate);
                unitOfWork.Save();
                string sourceId = meterToCreate.Sources[0].Id;
                int energyItems = 1;
                DateTime dateTimeNow = DateTime.Now;
                var energyDataFirst = InMemoryTestHelpers.MultipleEnergyDataItems(dateTimeNow, new TimeSpan(0, 0, 6), energyItems, 100);
                var energyDataSecond = InMemoryTestHelpers.MultipleEnergyDataItems(dateTimeNow, new TimeSpan(0, 0, 6), energyItems, 200);
                InMemoryEnergyDataRepository energyRepository = new InMemoryEnergyDataRepository(unitOfWork);
                energyRepository.SaveEnergyData(sourceId, energyDataFirst);
                energyRepository.SaveEnergyData(sourceId, energyDataSecond);
                unitOfWork.Save();
                var attachedEnergyData = unitOfWork.SavedEnergyDatum.Where(ed => ed.MeterSource.Id == sourceId).FirstOrDefault().EnergyDatum;
                Assert.AreEqual(energyItems, attachedEnergyData.Count());
            }

        }
    }
}
